package com.pool.activity;

import java.util.Date;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;

import com.pool.activity.common.FullscreenActivity;
import com.pool.common.Lists;
import com.pool.common.Maps;
import com.pool.common.Pair;
import com.pool.common.Record;
import com.pool.common.Shoot;
import com.pool.store.RecordStore;
import com.pool.store.ShootStore;
import com.pool.store.Store;

/**
 * Graphs of the points over time.
 * 
 * @author claveld@gmail.com (David Clavel)
 */
public class PointsOverTime extends FullscreenActivity {

  private static final int MARGIN = 5;
  private static final int[] COLORS = {Color.RED, Color.BLUE, Color.GREEN};
  
  private final Store<Record> permanentRecordStore;
  private final Store<Shoot> shootStore;

  public PointsOverTime() {
    this(RecordStore.usingPermanentTable(), new ShootStore());
  }
  
  public PointsOverTime(Store<Record> permanentRecordStore, Store<Shoot> shootStore) {
    this.permanentRecordStore = permanentRecordStore;
    this.shootStore = shootStore;
  }
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    ImageView imageView = new MyImageView(this);
    setContentView(imageView);
  }

  private class MyImageView extends ImageView {

    public MyImageView(Context context) {
      super(context);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      Paint axisPaint = new Paint();
      axisPaint.setColor(Color.WHITE);
      axisPaint.setStrokeWidth(2);
      axisPaint.setAntiAlias(true);
      
      int originX = MARGIN;
      int originY = originX;
      int width = canvas.getWidth() - MARGIN;
      int height = canvas.getHeight() - MARGIN;
      canvas.drawLine(originX, originY, width, originY, axisPaint);
      canvas.drawLine(originX, originY, originX, height, axisPaint);

      List<Record> records = permanentRecordStore.getAll();
      long minTimestamp = Date.parse(records.get(0).timestamp);
      long maxTimestamp = Date.parse(records.get(records.size() - 1).timestamp);
      
      // Extracting data points.
      Map<String, List<Pair<Long, Integer>>> points = Maps.newHashMap();
      Map<String, Integer> currentScores = Maps.newHashMap();
      Map<String, Integer> maxScores = Maps.newHashMap();
      Map<String, Integer> minScores = Maps.newHashMap();
      
      for (Record record : records) {
        String player = record.player;
        if (!points.containsKey(player)) {
          points.put(player, Lists.<Pair<Long, Integer>>newArrayList());
          currentScores.put(player, 0);
          minScores.put(player, Integer.MAX_VALUE);
          maxScores.put(player, Integer.MIN_VALUE);
        }
        int currentScore = currentScores.get(player);
        int minScore = minScores.get(player);
        int maxScore = maxScores.get(player);
        
        currentScore += shootStore.get(record.shootId).bonus;
        minScore = Math.min(minScore, currentScore);
        maxScore = Math.max(maxScore, currentScore);
        
        currentScores.put(player, currentScore);
        minScores.put(player, minScore);
        maxScores.put(player, maxScore);
        
        long timestamp = Date.parse(record.timestamp);
        points.get(player).add(Pair.of(timestamp, currentScore));
      }

      // Get Y boundaries.
      int absoluteMaxScore = Integer.MIN_VALUE;
      int absoluteMinScore = Integer.MAX_VALUE;
      for (String player : currentScores.keySet()) {
        absoluteMaxScore = Math.max(absoluteMaxScore, currentScores.get(player));
        absoluteMinScore = Math.min(absoluteMinScore, currentScores.get(player));
      }
      
      // Convert data points to screen points and drawing.
      int playerIndex = 0;
      for (String player : points.keySet()) {
        float previousX = MARGIN;
        float previousY = MARGIN;
        Paint paint = new Paint();
        paint.setColor(COLORS[playerIndex]);
        playerIndex++;
        
        for (Pair<Long, Integer> dataPoint : points.get(player)) {
          float x = getXOnScreen(dataPoint.getFirst(), minTimestamp, maxTimestamp, MARGIN, height);
          float y = getYOnScreen(dataPoint.getSecond(), absoluteMinScore - 1, absoluteMaxScore + 1, MARGIN, width);
          
          Log.i("DRAW", "from: " + previousX + ":" + previousY + "  to  " + x + ":" + y);
          canvas.drawLine(previousY, previousX, y, x, paint);
          previousX = x;
          previousY = y;
        }
      }
    }
    
    private float getXOnScreen(long timestamp, long minTimestamp, long maxTimestamp, int minX, int maxX) {
      return ((float)(timestamp - minTimestamp) / (float)(maxTimestamp - minTimestamp)) * (maxX - minX) + minX;
    }
    
    private float getYOnScreen(int value, int minValue, int maxValue, int minY, int maxY) {
      return ((float)(value - minValue) / (float)(maxValue - minValue)) * (- maxY + minY) + minY;
    }
  }
}
